{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c575f971-4ddd-4e58-b691-9b10ee892d31",
   "metadata": {},
   "source": [
    "# 8. 人工神经网络优化\n",
    "\n",
    "- 小批量梯度下降\n",
    "- 指数衰减学习率\n",
    "- 自定义损失函数\n",
    "- SGD优化器\n",
    "- SGDM优化器\n",
    "- Adagrad优化器\n",
    "- RMSProp优化器\n",
    "- Adam优化器\n",
    "- 正则化"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1f20875-c50d-46df-906b-49ec1d0c6002",
   "metadata": {},
   "source": [
    "# 8.1 使用小批量梯度下降算法训练模型\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c90a18b9-d8e8-431c-856c-35f1e4ed05e1",
   "metadata": {},
   "source": [
    "### 1.任务描述\n",
    "\n",
    "- 下载波士顿房价数据集\n",
    "- 选择训练集的房间数作为样本特征、训练集房价作为标签，构建一元线性回归模型\n",
    "- 使用小批量梯度下降算法训练模型，优化参数，批的大小设置为64\n",
    "- 绘制可视化损失曲线\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f5b4fc39-cbcf-432a-bf1e-e75e642d4b87",
   "metadata": {},
   "source": [
    "### 2.知识准备\n",
    "\n",
    "见教程。 \n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "b624ebee-980f-4c1e-b963-a24ff0b669f6",
   "metadata": {},
   "source": [
    "### 3.任务分析\n",
    "\n",
    "数据集共有506个样本，每个样本有14个属性，其中，第6个属性为房间数，第14个属性为房价，可以通过数据部分采样，将房间数作为样本特征，将房价作为样本标签，构建房间数与房价之间的一元线性模型：$y=wx+b$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "435c6090-cfda-4f46-a550-22a368e41e4a",
   "metadata": {},
   "source": [
    "### 4.任务实施\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ec75eb6c-5da3-467d-a471-ca3b47242dd6",
   "metadata": {},
   "source": [
    "执行代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "2ae9da58-e339-4d22-9f8d-ca255711d89e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch: 0 step: 0 ,loss_train 286.8636 ,w: 1.3884121 ,b: -0.93916357\n",
      "epoch: 0 step: 4 ,loss_train 44.48419 ,w: 3.439804 ,b: -0.63663006\n",
      "epoch: 1 step: 0 ,loss_train 30.780502 ,w: 3.5841813 ,b: -0.62418276\n",
      "epoch: 1 step: 4 ,loss_train 35.20822 ,w: 3.707656 ,b: -0.6227125\n",
      "epoch: 2 step: 0 ,loss_train 31.143608 ,w: 3.6469007 ,b: -0.64287734\n",
      "epoch: 2 step: 4 ,loss_train 35.065254 ,w: 3.7190394 ,b: -0.64940906\n",
      "epoch: 3 step: 0 ,loss_train 31.153397 ,w: 3.6529007 ,b: -0.67042005\n",
      "epoch: 3 step: 4 ,loss_train 35.04567 ,w: 3.7236001 ,b: -0.67716163\n",
      "epoch: 4 step: 0 ,loss_train 31.148735 ,w: 3.657389 ,b: -0.69817424\n",
      "epoch: 4 step: 4 ,loss_train 35.029305 ,w: 3.7279758 ,b: -0.70491844\n",
      "epoch: 5 step: 0 ,loss_train 31.143702 ,w: 3.6618333 ,b: -0.72591025\n",
      "epoch: 5 step: 4 ,loss_train 35.01305 ,w: 3.7323427 ,b: -0.7326516\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x211bcf42fd0>]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 600x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import tensorflow as tf\n",
    "# 处理中文乱码\n",
    "plt.rcParams['font.sans-serif']=['SimHei']\n",
    "plt.rcParams['axes.unicode_minus']=False\n",
    "# 1，加载数据\n",
    "(train_x,train_y),(test_x,test_y)=tf.keras.datasets.boston_housing.load_data()\n",
    "\n",
    "# 2，数据预处理\n",
    "# 2.1，获取样本特征（房间数）\n",
    "X_train=train_x[:,5]\n",
    "# 2.2，获取样本标签（房价）\n",
    "Y_train=train_y\n",
    "\n",
    "# 2.3，转换类型\n",
    "X_train = tf.cast(X_train, tf.float32)\n",
    "Y_train = tf.cast(Y_train, tf.float32)\n",
    "\n",
    "# 函数切分传入的张量的第一个维度，生成数据集，使输入特征和标签值一一对应\n",
    "train_db = tf.data.Dataset.from_tensor_slices((X_train, Y_train)).batch(64)\n",
    "# 3，设置超参数\n",
    "# 学习率\n",
    "lr = 0.01  \n",
    "# 循环轮数\n",
    "epoch = 5\n",
    "# 显示频率\n",
    "display_step=4\n",
    "# 参数初始化\n",
    "np.random.seed(612)\n",
    "w=tf.Variable(np.random.randn())\n",
    "b=tf.Variable(np.random.randn())\n",
    "\n",
    "# 4，训练模型\n",
    "mse_train=[]\n",
    "\n",
    "for epoch in range(epoch+1):\n",
    "    for step,(x_train,y_train) in enumerate(train_db):\n",
    "        with tf.GradientTape() as tape:\n",
    "            # 预测值\n",
    "            PRED_train=w*x_train+b\n",
    "            # 均方误差损失函数，训练误差\n",
    "            loss_train=0.5 * tf.reduce_mean(tf.square(y_train-PRED_train))\n",
    "        # 添加到训练误差列表\n",
    "        mse_train.append(loss_train)\n",
    "        # 对w和b求偏导数\n",
    "        dL_dw,dL_db=tape.gradient(loss_train,[w,b])\n",
    "        # 更新参数\n",
    "        w.assign_sub(lr*dL_dw)\n",
    "        b.assign_sub(lr*dL_db)\n",
    "        # 打印损失\n",
    "        if step%display_step == 0:\n",
    "            print('epoch:',epoch,'step:',step,',loss_train',loss_train. numpy(),',w:',w.numpy(),',b:',b.numpy())\n",
    "\n",
    "# 5，可视化损失\n",
    "plt.figure(figsize=(6,4))\n",
    "plt.xlabel(\"迭代次数\",fontsize='large')\n",
    "plt.ylabel(\"损失\",fontsize='large')\n",
    "plt.plot(mse_train,color='blue',label=\"train_loss\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3b3e36e-8418-4caf-af51-d8ac80e2a321",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
